const fs = require('fs');
const path = require('path');
const template = require('art-template');
const zipper = require("zip-local");
const db = require('./db')

// 生成文件夹
const generatorPath = path.join(__dirname, '../generator')
// 生成文件压缩包
const generatorZipPath = path.join(__dirname, '../generator.zip')
// 模板文件夹
const templatePath = path.join(__dirname, '../template')
// 表前缀
const tablePrefix = ['t_']

module.exports = {
  /**
   * 生成方法
   * @param {*} tableName
   * @returns
   */
  async generator(table) {
    let templateData = await formatTableInfoData(table)
    let c = fs.readFileSync(path.join(__dirname, '../configs/writeFiles.json'), "utf-8")
    let a = c.split('// -------- split line -------- //')[1]
    let writeFilesConfig = JSON.parse(a)
    // console.log(writeFilesConfig)
    // return false

    // 封装生成文件数据 fileName文件名，fileFolder文件夹名，fileContent文件内容模板
    try {
      let writeFiles = writeFilesConfig.map(item => {
        // 生成需要拼接表名的文件
        if (item.fileName.substr(0, 1) == ".") {
          item.fileName = camelCase(table.tableName) + item.fileName
        }
        if (item.templateFileName) {
          item.fileContent = getTemplate(item.templateFileName, templateData)
        } else {
          item.fileContent = getTemplate(item.fileName, templateData)
        }
        return item
      })
      let flag = await batchWriteFile(table.tableName, writeFiles)
      return flag
    } catch (error) {
      throw error
    }
  },
  /**
   * 表批量生成
   * @param {*} tables
   * @returns
   */
  async batchGenerator(tables) {
    let flag = await exists(generatorPath)
    let Zipflag = await exists(generatorZipPath)
    // 删除生成文件夹
    if (flag) {
      await delDir(generatorPath)
    }
    // 删除生成文件夹压缩包
    if (Zipflag) {
      fs.unlinkSync(generatorZipPath)
    }
    // 创建generator文件夹
    await mkdir('generator')
    // 返回生成
    try {
      let suc = []
      let unsuc = []
      for (let item of tables) {
        let flag = await this.generator(item)
        if (flag) {
          suc.push(item.tableName)
        } else {
          unsuc.push(item.tableName)
        }
      }
      return {
        suc: suc,
        unsuc: unsuc
      }
    } catch (error) {
      throw error
    }
  },
  // 下载压缩包
  async downloadZip() {
    zipper.sync.zip(path.join(__dirname, '../generator')).compress().save(path.join(__dirname, '../generator.zip'));
    let flag = await exists(generatorZipPath)
    if (flag) {
      return path.join(__dirname, '../generator.zip')
    } else {
      return null
    }
  },
  /**
   * 获取文件夹下文件
   * @param {*} folderName
   * @returns
   */
  getFiles(folderName) {
    let p = path.join(__dirname, '../' + folderName)
    let files = fs.readdirSync(p);
    let res = []
    for (let item of files) {
      let c = fs.readFileSync(p + '/' + item, "utf-8")
      res.push({
        fileName: item,
        fileContent: c
      })
    }
    return res
  },
  /**
   * 更新文件类容
   * @param {*} params folderName fileName fileContent
   */
  updateFile(params) {
    let p = path.join(__dirname, '../' + params.folderName)
    fs.writeFileSync(p + '/' + params.fileName, params.fileContent, 'utf8')
  }
}

/**
 * 检测文件夹是否存在
 * @returns
 */
function exists(path) {
  return new Promise((res) => {
    (async function () {
      let flag = fs.existsSync(path);
      res(flag);
    })()
  })
}

/**
 * 删除文件夹
 * @param {*} path
 */
function delDir(path) {
  return new Promise((res, rej) => {
    (async function () {
      let files = [];
      if (fs.existsSync(path)) {
        files = fs.readdirSync(path);
        files.forEach((file, index) => {
          let curPath = path + "/" + file;
          if (fs.statSync(curPath).isDirectory()) {
            delDir(curPath); //递归删除文件夹
          } else {
            fs.unlinkSync(curPath); //删除文件
          }
        });
        fs.rmdirSync(path);
      }
      res('succ');
    })()
  })
}

/**
 * 在根目录下创建文件夹
 * @param {*} name
 * @returns
 */
function mkdir(name) {
  return new Promise(async (res, rej) => {
    let p = path.join(__dirname, '../' + name)
    fs.mkdir(p, (err) => {
      if (err) {
        res(err)
      }
      res(p);
    });
  })
}

/**
 * 获取模板内容
 * @param {*} templateFile 模板文件名称
 * @param {*} tempData 模板数据
 * @returns
 */
function getTemplate(templateFile, tempData) {
  if (!templateFile) {
    console.error('缺少模板文件！')
    return
  }
  if (!tempData) {
    console.error('缺少模板数据！')
    return
  }
  try {
    return template(`${templatePath}/${templateFile}`, tempData);
  } catch (error) {
    throw error
  }
}

/**
 * 批量创建文件
 * @param {*} writes [] {fileName 需要创建的文件名 fileContent 通过模板生成的}
 * @returns
 */
function batchWriteFile(tableName, writes) {
  if (!tableName) {
    console.error('缺少模块名称！')
    return
  }
  if (!writes) {
    console.error('缺少生成文件数据！')
    return
  }
  return new Promise((res, rej) => {
    (async function () {
      // 创建模块文件夹
      let dir = camelCase(tableName)
      let p = await mkdir('/generator/' + dir)
      if (p) {
        for (let item of writes) {
          let itemPath = `${generatorPath}/${dir}/${item.fileName}`
          if (item.fileFolder) {
            let fileFolderPath = await mkdir(`/generator/${dir}/${item.fileFolder}`)
            itemPath = `${generatorPath}/${dir}/${item.fileFolder}/${item.fileName}`
          }
          fs.writeFile(itemPath, item.fileContent, (err) => {
            if (err) {
              res(false)
              console.log(err)
            }
          })
        }
      }
      res(true);
    })()
  })
}

/**
 * 转化驼峰
 * @param {*} str
 * @returns
 */
function camelCase(str) {
  str = formatTableName(str)
  var strArr = str.split('_');
  for (var i = 1; i < strArr.length; i++) {
    strArr[i] = strArr[i].charAt(0).toUpperCase() + strArr[i].substring(1);
  }
  return strArr.join('');
}

/**
 * 格式化表名称 去掉前缀
 * @param {*} name
 */
function formatTableName(name) {
  let tablePrefixParam =  []
  console.log('global.tablePrefix', global.tablePrefix)
  if(global.tablePrefix){
    tablePrefixParam = global.tablePrefix?.split(',')
  }
  console.log('tablePrefixParam', tablePrefixParam)

  let pre = [...tablePrefixParam, ...tablePrefix].find(item => name.startsWith(item))
  console.log('prefix', pre)
  if (pre) {
    let reg = new RegExp(`${pre}`);
    return name.replace(reg, '')
  }
  return name
}

/**
 * 格式话表详情数据
 */
async function formatTableInfoData(table) {
  // 查询数据库查询表信息封装模板数据
  let sql = `SELECT *
             FROM information_schema.COLUMNS
             WHERE TABLE_SCHEMA = '${global.database}'
               AND TABLE_NAME = '${table.tableName}';`
  let tableDetailData = await db.query(sql)
  // 模板数据
  let res = {
    tableName: camelCase(table.tableName),
    tableComment: table.tableComment,
    tableColumns: function fn(data) {
      if (data) {
        // 排出字段
        let expelColumn = ['f_tenant_id', 'f_deleted', 'f_version']
        let reg = new RegExp(`f_`);
        let temp = data.filter(item => !expelColumn.includes(item.COLUMN_NAME))
        let res = temp.map(item => {
          let o = {
            "columnComment": item.COLUMN_COMMENT,
            "columnName": camelCase(item.COLUMN_NAME.replace(reg, '')),
            "columnType": item.COLUMN_TYPE,
          }
          // 获取字符类型添加长度
          let s = o.columnType.match(/\(([^)]*)\)/)
          if (s) {
            o.columnLength = s[1]
          } else {
            o.columnLength = 50
          }
          return o
        })
        console.log(res)
        return res
      } else {
        return []
      }
    }(tableDetailData.aaData)
  }
  return res
}
